#include "Poller.hpp"
#include "Channel.hpp"

#include <sys/epoll.h>
#include <unistd.h>
#include <cassert>
#include <cstring>
#include <iostream>

Poller::Poller()
    : epollfd_(::epoll_create1(EPOLL_CLOEXEC)),
      events_(kInitEventListSize) {
    if (epollfd_ < 0) {
        perror("epoll_create1");
        abort();
    }
}

Poller::~Poller() {
    ::close(epollfd_);
}

void Poller::poll(int timeoutMs, std::vector<Channel*>& activeChannels) {
    int numEvents = ::epoll_wait(epollfd_,
                                  events_.data(),
                                  static_cast<int>(events_.size()),
                                  timeoutMs);

    if (numEvents < 0) {
        perror("epoll_wait error");
        return;
    }

    for (int i = 0; i < numEvents; ++i) {
        Channel* channel = static_cast<Channel*>(events_[i].data.ptr);
        channel->setRevents(events_[i].events);
        activeChannels.push_back(channel);
    }

    // 如果触发的事件数等于数组容量，扩容
    if (numEvents == events_.size()) {
        events_.resize(events_.size() * 2);
    }
}

void Poller::updateChannel(Channel* channel) {
    int fd = channel->fd();
    int events = channel->events();

    if (channels_.count(fd) == 0) {
        // 新的 channel，添加
        channels_[fd] = channel;
        update(EPOLL_CTL_ADD, channel);
    } else {
        update(EPOLL_CTL_MOD, channel);
    }
}

void Poller::removeChannel(Channel* channel) {
    int fd = channel->fd();
    assert(channels_.count(fd));
    update(EPOLL_CTL_DEL, channel);
    channels_.erase(fd);
}

void Poller::update(int operation, Channel* channel) {
    struct epoll_event ev;
    std::memset(&ev, 0, sizeof(ev));
    ev.events = channel->events();
    ev.data.ptr = channel;

    int fd = channel->fd();
    if (::epoll_ctl(epollfd_, operation, fd, &ev) < 0) {
        perror("epoll_ctl failed");
    }
}
